

import Wxapi from './wxapi';
import ByteDance from './byteDance';
import WebTest from './baseClient';
import Utils from '../utils';
import http from './HTTP';
import DateUtils  from '../date_utils';
import AndroidApi from './androidApi';

// 游戏配置
import GameConfig from './gameconfig';

// 游戏数据
import GameData from './gamedata';

import { version} from '../../package.json';


/**
 *  包含一些通用的方法
 *  @namespace
 */
let ShSdk = {

    /**
     * shsdk版本
     * @type {string}
     * @const
     **/
    _version:version,

    /**
     * 各个平台的具体实现, 继承自 BasicClient
     * @type {obejct}
     */
    _client:null,

    /**
     * cc.winSize 的引用
     */
    _winSize:null,

    /**
     * 屏幕中心为原点时,屏幕最上方的y坐标.
     * @type {number}
     */
    _maxY:0,

    /**
     * 屏幕中心为原点时,屏幕最下方的y坐标.
     * @type {number}
     */
    _minY:0,

    /**
     * 游戏界面参考的坐标系. 屏幕中最上面的y坐标
     * @type {number}
     */
    _maxGameY:0,

    /**
     * 游戏界面参考的坐标系. 屏幕中最下面的y坐标
     * @type {number}
     */
    _minGameY:0,

    /**
     * 设计分辨率宽
     * @type {number}
     */
    _devWidth:0,

    /**
     * 设计分辨率高
     * @type {number}
     */
    _devHeight:0,

    /**
     * 指向各个平台的配置
     * @type {object}
     */
    config:null,


    /**
     *  added v1.0.5
     *  调用时间在 init 后, 加载配置和数据之前.
     *  目的是,从这里开始可以判断手机是否是刘海屏,知道手机大小. 可以在耗时的操作前进行一些适配工作.
     */
    beforeLoadCb:null,
    updateDataCb:null, // 当数据发生变化的时候.  即 GameData._dumpLocalData 调用的时候,需要进行回掉

    /**
     * 每日更新的数据
     * @type {obejct}
     */
    dailyConfig:{
        stamp:DateUtils.getDayStamp(),
        gamingVideo:0,  //游戏中看视频的金币的次数
        playDay:1, // 累计游戏天数
        flYaoq: 0,    //---每日邀请新玩家人数
        flPull: 0,   //----每日激活老玩家人数
    },

    /**
     * 设置设计分辨率
     * @param w {number} 设计分辨率宽
     * @param h {number} 设计分辨率高
     */
    setDevSize(w,h){
        this._devWidth = w;
        this._devHeight = h;
    },

    /**
     * 程序初始化
     * @param defaultLocalData {object} 默认的本地数据
     * @param defaultPlayerData {object} 默认的玩家数据,需要上传到服务器
     * @param cb {Function} 初始化完毕的回调函数
     */
    init(defaultLocalData,defaultPlayerData,cb){

        Utils.asset(this.config,'config 不能为空, 请先设置 ShSdk.config');
        Utils.asset(this.config.serverConfig,'serverConfig 不能为空');
        Utils.asset(this._devWidth > 0, 'devWidth 应该 >=0.请先调用 setDevSize');
        Utils.asset(this._devHeight > 0, '_devHeight 应该 >=0.请先调用 setDevSize');
        Utils.asset(this.config.httpUrl,'httpUrl 不能为空!');
        Utils.asset(this.config.configFile,'configFile 不能为空!');

        //
        let winSize = this._winSize = cc.winSize;
        this._maxY = winSize.height / 2;
        this._minY = - winSize.height / 2;
        this._maxGameY = this._maxY + this._devHeight / 2;
        this._minGameY = this._devHeight/2 - this._maxY;

        http.configURL(this.config.httpUrl);

        let cfgName = this.config.configFile;
        let saveType = this.config.saveType;
        if(this.isWeChat()){
            // 抖音
            this._client = new Wxapi(this.config);
        }else if(this.isByteDance()){
            this._client = new ByteDance(this.config);
        }else if(this.isWebTest()){
            this._client = new WebTest(this.config);
        }else if(this.isAndroid() && cc.sys.isNative){
            this._client = new AndroidApi(this.config);
        }else{
            // TODO: 相应的平台实现
            throw new Error(`请实现相应的平台......`);
        }

        Utils.asset(this._client,'client 不能为空!');

        // 配置
        // 加载配置文件
        this._client.init();

        if(this.beforeLoadCb && Types.isFunction(this.beforeLoadCb)){
            this.beforeLoadCb();
        }

        GameConfig.loadConfig(cfgName);

        // 数据
        // 加载数据
        GameData.setDefaultData(defaultLocalData,defaultPlayerData);
        GameData.loadData(this._client,saveType,cb);
    },

    onUpdateData(){
        if(this.updateDataCb && Types.isFunction(this.updateDataCb)){
            this.updateDataCb();
        }
    },

    /**
     * 判断是否为刘海屏
     * @return {boolean} true 表示刘海屏 false 表示非刘海屏
     */
    isLiuhaiScreen(){
        return (this._maxY * 2 - this._devHeight >= 100);
    },

    /**
     * 返回对应平台的实现
     * @return {obejct}
     */
    getClient(){
        return this._client;
    },

    //----------------------------
    /**
     * {@link ShSdk._minY}
     * @return {number}
     */
    getMinY(){
        return this._minY;
    },

    /**
     * {@link ShSdk._maxY}
     * @return {number}
     */
    getMaxY(){
        return this._maxY;
    },

    /**
     * {@link ShSdk._minGameY}
     * @return {number}
     */
    getMinGameY(){
        return this._minGameY;
    },

    /**
     * {@link ShSdk._maxGameY}
     * @return {number}
     */
    getMaxGameY(){
        return this._maxGameY;
    },

    getDevWidth(){
        return this._devWidth;
    },

    getDevHeight(){
        return this._devHeight;
    },

    getWinSize(){
        return this._winSize;
    },

    //----------------------------
    // platform
    /**
     * 是否是微信平台
     * @return {boolean}
     */
    isWeChat(){
        return cc.sys.platform === cc.sys.WECHAT_GAME;
    },

    /**
     * 是否是抖音平台
     * @return {boolean}
     */
    isByteDance (){
        return cc.sys.platform === cc.sys.BYTEDANCE_GAME;
    },

    /**
     * 是否是web测试平台.
     * @return {boolean}
     */
    isWebTest(){
        return cc.sys.platform === cc.sys.MOBILE_BROWSER;
    },

    /**
     * 是否是微信pc端
     * @return {boolean}
     */
    isPCWeChat(){
        if(this.isWeChat() && window.wx){
            if(!window._$sysinfo$_){
                window._$sysinfo$_ = wx.getSystemInfoSync();
            }
            return 'windows' === window._$sysinfo$_.platform;
        }
        return false;
    },

    //  系统判断
    /**
     * 是否是 android 平台
     * @return {boolean}
     */
    isAndroid(){
        return cc.sys.os === cc.sys.OS_ANDROID;
    },

    /**
     * 是否是 ios 平台
     * @return {boolean}
     */
    isIOS(){
        return cc.sys.os === cc.sys.OS_IOS;
    },

    // 分享失败提示
    /**
     * 分享失败提示
     * @param msg {string}
     */
    shareFailTip(msg){
        console.log(`分享失败提示:${msg}`);
    },

    // 获取广告失败提示
    /**
     * 获取 视频广告 失败提示
     * @param msg {string}
     */
    getVideoFailTip(msg){
        console.log(`获取视频广告失败提示:${msg}`);
    },

    // 视频没有播放完毕提示
    /**
     * 视频没有播放完毕提示
     * @param msg {string}
     */
    videoUnFinishTip(msg){
        console.log(`视频没有播放完毕提示:${msg}`);
    },

    // for test
    // 需要将游戏坐标转换成 广告坐标
    // pos 参考的是 中心点位屏幕中心的坐标系
    // ccPosToCanvas(pos) {
    //     this._sysInfo = wx.getSystemInfoSync();
    //     const winSize = ShSdk.getWinSize();
    //     let x = this._sysInfo.windowWidth * (pos.x + winSize.width / 2) / winSize.width;
    //     let y = this._sysInfo.windowHeight - this._sysInfo.windowHeight * (pos.y + winSize.height / 2) / winSize.height;
    //     return {x: x, y: y};
    // },
    // ccSizeToCanvas(size) {
    //     this._sysInfo = wx.getSystemInfoSync();
    //     const winSize = ShSdk.getWinSize();
    //     let w = size.width * this._sysInfo.windowWidth / winSize.width;
    //     let h = size.height * this._sysInfo.windowHeight / winSize.height;
    //     return {width: w, height: h};
    // },
};

import MathUtils from '../math_utils';
import ArrayUtils from '../array_utils';
import ObjUtils from '../obj_utils';
import Types from '../types';
import MyBezier from '../ds/myBezier';
import LRUCache from '../ds/lruCache';
import Dispersed from '../gailv/dispersed';

// let numbers = require('numbers');

//========================================
// 暴露的工具
/**
 * 管理游戏数据.
 */
ShSdk.GameData = GameData;

/**
 * 游戏原生配置.
 */
ShSdk.GameConfig = GameConfig;

/**
 * 进行http请求
 */
ShSdk.HTTP = http;

/**
 * 一些常用方法
 */
ShSdk.Utils = Utils;

/**
 *  一些常用的数学方法
 */
ShSdk.MathUtils = MathUtils;

/**
 *  一些常用的数组方法
 */
ShSdk.ArrayUtils = ArrayUtils;

/**
 * 一些常用的日期方法
 */
ShSdk.DateUtils = DateUtils;

/**
 * 一些常用的对象方法
 */
ShSdk.ObjUtils = ObjUtils;

/**
 * 判断常用类型的方法
 */
ShSdk.Types =  Types;

/**
 * 二阶贝塞尔曲线方法
 */
ShSdk.MyBezier = MyBezier;

/**
 * LRCCache的简单实现
 */
ShSdk.LRUCache = LRUCache;

// 概率
ShSdk.Dispersed = Dispersed;

// ShSdk.numbers = numbers;


/**
 *  播放视频标识
 *  @type {number}
 *  @const
 *  */
ShSdk.OP_PLAY_VIDEO = 1; // 播放视频

/**
 * 分享标识
 * @type {number}
 * @const
 */
ShSdk.OP_SHARE = 2; // 分享

if(typeof window !== "undefined"){
    window.ShSdk = ShSdk;
}
export default ShSdk;
